import { AxiosRequestConfig, AxiosResponse } from "axios";
import { IErrorData, IResponseData } from "@/model/frame/ResponseModel";

/**
 * 在 Mock 状态时，判断 Mock 已经初始化完成
 * @constructor
 *
 * ```
 * @IsMockInit
 * List()
 * ```
 */
export function IsMockInit(
  target: any,
  propertyKey: string | symbol,
  descriptor: PropertyDescriptor
) {
  const originalMethod = descriptor.value;
  descriptor.value = function() {
    // 判断是否是 调试 模式
    if (
      process.env.NODE_ENV !== "production" &&
      !window.store.get<boolean>("app/mockInited")
    ) {
      return new Promise<IResponseData>((resolve, reject) => {
        const _error: IErrorData = {
          error: "ServerError",
          message: "Mock 未初始化 异常"
        };
        reject({
          code: 500,
          data: _error
        });
      });
    } else {
      // eslint-disable-next-line prefer-rest-params
      return originalMethod.apply(this, arguments);
    }
  };
  return descriptor;
}

export class APITool {
  static onAxiosReady(
    resolve: (value: PromiseLike<IResponseData> | IResponseData) => void,
    reject: (reason?: any) => void
  ) {
    return (res: AxiosResponse) => {
      console.log("[APITool]:", res);

      const data: IResponseData = res.data;
      if (res.status <= 299 || data.code <= 299) {
        resolve(data);
      } else {
        reject(data);
      }
    };
  }

  public static get(
    url: string,
    config?: AxiosRequestConfig
  ): Promise<IResponseData> {
    const _config: AxiosRequestConfig = { ...config };
    return new Promise<IResponseData>((resolve, reject) => {
      window.axios
        .get(url, _config)
        .then(APITool.onAxiosReady(resolve, reject))
        .catch(reason => {
          reject(reason);
        });
    });
  }

  public static post(
    url: string,
    data: any,
    config?: AxiosRequestConfig
  ): Promise<IResponseData> {
    const _config: AxiosRequestConfig = { ...config };
    return new Promise<IResponseData>((resolve, reject) => {
      window.axios
        .post(url, data, _config)
        .then(APITool.onAxiosReady(resolve, reject))
        .catch(reason => {
          reject(reason);
        });
    });
  }

  public static put(
    url: string,
    data: any,
    config?: AxiosRequestConfig
  ): Promise<IResponseData> {
    const _config: AxiosRequestConfig = { ...config };
    return new Promise<IResponseData>((resolve, reject) => {
      window.axios
        .put(url, data, _config)
        .then(APITool.onAxiosReady(resolve, reject))
        .catch(reason => {
          reject(reason);
        });
    });
  }

  public static delete(
    url: string,
    config?: AxiosRequestConfig
  ): Promise<IResponseData> {
    const _config: AxiosRequestConfig = { ...config };
    return new Promise<IResponseData>((resolve, reject) => {
      window.axios
        .delete(url, _config)
        .then(APITool.onAxiosReady(resolve, reject))
        .catch(reason => {
          reject(reason);
        });
    });
  }
}
